home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / text / psorder-.000 / psorder- / psorder-0.1.0 / psorder.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-06-07  |  8.4 KB  |  286 lines

  1. /* $Id: psorder.c,v 1.1.1.1 1996/06/07 01:00:44 sverrehu Exp $ */
  2. /**************************************************************************
  3.  *
  4.  *  FILE            psorder.c
  5.  *  MODULE OF       psorder - move negative pages in a .ps-file
  6.  *
  7.  *  DESCRIPTION     Program for moving negative numbered pages in a
  8.  *                  postscript-file to some given/suitable location.
  9.  *
  10.  *                  Primarily written to move the table of contents of
  11.  *                  files generated by texi2dvi -> dvips from the end
  12.  *                  of the file to after the title pages.
  13.  *
  14.  *  WRITTEN BY      Sverre H. Huseby <sverrehu@ifi.uio.no>
  15.  *
  16.  **************************************************************************/
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21.  
  22. #include <shhmsg.h>
  23. #include <shhopt.h>
  24.  
  25. #include "util.h"
  26.  
  27. #define MAXPAGES   2000
  28. #define MAXLINELEN 4096
  29.  
  30. #define PSID       "%!PS-Adobe-2.0"
  31. #define PSPAGE     "%%Page:"
  32. #define PSTRAIL    "%%Trailer"
  33. #define PSEOF      "%%EOF"
  34.  
  35. /**************************************************************************
  36.  *                                                                        *
  37.  *                       P R I V A T E    D A T A                         *
  38.  *                                                                        *
  39.  **************************************************************************/
  40.  
  41. static FILE *inFile, *outFile;
  42. typedef struct {
  43.     int  p1,            /* program generated page number */
  44.          p2;            /* page sequence number */
  45.     long start,         /* byte offset of this page */
  46.          nlines;        /* number of lines for this page */
  47. } psPage;
  48. static psPage page[MAXPAGES], *ordered[MAXPAGES];
  49. static int nPages = 0;
  50. static char line[MAXLINELEN + 1];
  51. static long offsTrail = 0L, nlinesHead = 0L;
  52.  
  53.  
  54.  
  55. /**************************************************************************
  56.  *                                                                        *
  57.  *                   P R I V A T E    F U N C T I O N S                   *
  58.  *                                                                        *
  59.  **************************************************************************/
  60.  
  61. /*-------------------------------------------------------------------------
  62.  *
  63.  *  NAME          scanFile
  64.  *
  65.  *  FUNCTION      Locate all pages in a PostScript-file.
  66.  *
  67.  *  SYNOPSIS      void scanFile(void);
  68.  *
  69.  *  DESCRIPTION   The file is left open, with the current location at the
  70.  *                end of the file. All pageinfo is stored in the global
  71.  *                structure.
  72.  *
  73.  */
  74. static void scanFile(void)
  75. {
  76.     long   l = 0L, last = 0L;
  77.     psPage *p;
  78.     
  79.     msgVerbose(1, "scanning file to find page offsets\n");
  80.     if (fgets(line, MAXLINELEN, inFile) == NULL)
  81.     msgFatal("unexpected end of file\n");
  82.     if (strncmp(line, PSID, strlen(PSID)) != 0)
  83.     msgFatal("input is not recognized as a PostScript-file\n");
  84.     while (fgets(line, MAXLINELEN, inFile) != NULL) {
  85.     if (strncmp(line, PSTRAIL, strlen(PSTRAIL)) == 0
  86.         || strncmp(line, PSEOF, strlen(PSEOF)) == 0)
  87.         break;
  88.     if (strncmp(line, PSPAGE, strlen(PSPAGE)) == 0) {
  89.         if (nPages == MAXPAGES)
  90.         msgFatal("too many pages.\n");
  91.         if (nPages)
  92.         page[nPages - 1].nlines = l - 1;
  93.         else
  94.         nlinesHead = l + 1;
  95.         l = 0L;
  96.         p = &page[nPages];
  97.         if (sscanf(line + strlen(PSPAGE), "%d %d\n", &p->p1, &p->p2) != 2)
  98.         msgFatal("two pagenumbers expected after %s\n", PSPAGE);
  99.         p->start = ftell(inFile);
  100.         ++nPages;
  101.     }
  102.     ++l;
  103.     last = ftell(inFile);
  104.     }
  105.     if (!nPages)
  106.     msgFatal("no pagestarts recognized in input\n");
  107.     page[nPages - 1].nlines = l - 1;
  108.     offsTrail = last;
  109. }
  110.  
  111.  
  112.  
  113. /*-------------------------------------------------------------------------
  114.  *
  115.  *  NAME          arrangePages
  116.  *
  117.  *  FUNCTION      Arrange the pages in `correct' order.
  118.  *
  119.  *  SYNOPSIS      void arrangePages(int pageno);
  120.  *
  121.  *  INPUT         pageno  The new number of the first negative page,
  122.  *                        counting from 1.
  123.  *
  124.  */
  125. static void arrangePages(int pageno)
  126. {
  127.     int n, q;
  128.     
  129.     if (pageno < 0) {
  130.     /*
  131.          *  find a suitable location.
  132.          *  for files generated by texi2dvi -> dvips, this is where
  133.          *  the page counter starts at 1 the second time.
  134.          */
  135.     for (q = 1; q < nPages; q++)
  136.         if (page[q].p1 == 1)
  137.         break;
  138.     if (q == nPages)
  139.         msgFatal("unable to find good location for the negative pages.\n");
  140.     pageno = page[q].p2;
  141.     msgVerbose(1, "negative pages will be inserted from page %d\n",
  142.            pageno);
  143.     }
  144.     msgVerbose(1, "rearranging\n");
  145.     for (q = 0; q < pageno - 1; q++)
  146.     ordered[q] = &page[q];
  147.     for (n = q = pageno - 1 ; q < nPages; q++)
  148.     if (page[q].p1 < 0)
  149.         ordered[n++] = &page[q];
  150.     for (q = pageno - 1 ; q < nPages; q++)
  151.     if (page[q].p1 >= 0)
  152.         ordered[n++] = &page[q];
  153.     for (q = 0; q < nPages; q++)
  154.     ordered[q]->p2 = q + 1;
  155. }
  156.  
  157.  
  158.  
  159. /*-------------------------------------------------------------------------
  160.  *
  161.  *  NAME          writeFile
  162.  *
  163.  *  FUNCTION      Output the pages in the current order.
  164.  *
  165.  *  SYNOPSIS      void writeFile(void);
  166.  *
  167.  */
  168. static void writeFile(void)
  169. {
  170.     int    q, w;
  171.     psPage *p;
  172.     
  173.     msgVerbose(1, "writing rearranged pages\n");
  174.     rewind(inFile);
  175.     for (q = 0; q < nlinesHead; q++) {
  176.     if (fgets(line, MAXLINELEN, inFile) == NULL)
  177.         msgFatal("unexpected end of file\n");
  178.     if (fputs(line, outFile) == EOF)
  179.         msgFatalPerror("fputs");
  180.     }
  181.     for (q = 0; q < nPages; q++) {
  182.     p = ordered[q];
  183.     fseek(inFile, p->start, SEEK_SET);
  184.     fprintf(outFile, "%s %d %d\n", PSPAGE, p->p1, p->p2);
  185.     for (w = 0; w < p->nlines; w++) {
  186.         if (fgets(line, MAXLINELEN, inFile) == NULL)
  187.         msgFatal("unexpected end of file\n");
  188.         if (fputs(line, outFile) == EOF)
  189.         msgFatalPerror("fputs");
  190.     }
  191.     }
  192.     fseek(inFile, offsTrail, SEEK_SET);
  193.     while (fgets(line, MAXLINELEN, inFile) != NULL)
  194.     if (fputs(line, outFile) == EOF)
  195.         msgFatalPerror("fputs");
  196.     fclose(outFile);
  197.     fclose(inFile);
  198. }
  199.  
  200.  
  201.  
  202. /*-------------------------------------------------------------------------
  203.  *
  204.  *  NAME          usage
  205.  *
  206.  *  FUNCTION      Display usage, and abort program.
  207.  *
  208.  *  RETURNS       Never returns.
  209.  *
  210.  */
  211. static void usage(void)
  212. {
  213.     printf(
  214.       "usage: %s [option ...] [infile [outfile]]\n"
  215.       "\n"
  216.       "  -p, --page-number=NUM   set new page number of first negative page\n"
  217.       "  -f, --force             force overwrite of existing file\n"
  218.       "  -v, --verbose           verbosly list what is going on\n"
  219.       "  -h, --help              display this help and exit\n"
  220.       "  -V, --version           output version information and exit\n"
  221.       "\n"
  222.       "If no --page-number is given, the program tries to find a good place.\n"
  223.       "\n",
  224.       msgGetName()
  225.     );
  226.     exit(0);
  227. }
  228.  
  229.  
  230.  
  231. /*-------------------------------------------------------------------------
  232.  *
  233.  *  NAME          version
  234.  *
  235.  *  FUNCTION      Display version information, and abort program.
  236.  *
  237.  *  RETURNS       Never returns.
  238.  *
  239.  */
  240. static void version(void)
  241. {
  242.     printf("%s " VERSION " by Sverre H. Huseby, Norway\n", msgGetName());
  243.     exit(0);
  244. }
  245.  
  246.  
  247.  
  248. /**************************************************************************
  249.  *                                                                        *
  250.  *                    P U B L I C    F U N C T I O N S                    *
  251.  *                                                                        *
  252.  **************************************************************************/
  253.  
  254. int main(int argc, char *argv[])
  255. {
  256.     static int verbose = 0, force = 0, pageNumber = -1;
  257.     optStruct opt[] = {
  258.       /* short long           type        var/func    special       */
  259.         { 'p', "page-number", OPT_INT,    &pageNumber,0            },
  260.         { 'f', "force",       OPT_FLAG,   &force,     0            },
  261.         { 'v', "verbose",     OPT_FLAG,   &verbose,   0            },
  262.         { 'h', "help",        OPT_FLAG,   usage,      OPT_CALLFUNC },
  263.         { 'V', "version",     OPT_FLAG,   version,    OPT_CALLFUNC },
  264.         { 0, 0, OPT_END, 0, 0 }  /* no more options */
  265.     };
  266.     
  267.     msgSetName(argv[0]);
  268.     optParseOptions(&argc, argv, opt, 0);
  269.     msgSetVerbose(verbose);
  270.  
  271.     if (argc == 1) {
  272.     inFile = fileOpenReadSeekable(NULL);
  273.     outFile = fileOpenWrite(NULL, force);
  274.     } else if (argc <= 3) {
  275.     inFile = fileOpenReadSeekable(argv[1]);
  276.     outFile = fileOpenWrite(argc == 2 ? NULL : argv[2], force);
  277.     } else
  278.     usage();
  279.  
  280.     scanFile();
  281.     arrangePages(pageNumber);
  282.     writeFile();
  283.  
  284.     return 0;
  285. }
  286.